﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Collections.ObjectModel;

using System.Threading;
using Saber.Infrastructure.Logger;
using Saber.Plugin.NtfsSearch.QueryEngine;
using UsnOperation;
using System.ComponentModel;
using System.Threading.Tasks;

namespace Saber.Plugin.NtfsSearch
{
    public class LoadingDriverInfo
    {
        public string Name { get; set; }

        public string DriveFormat { get; set; }

        public UsnErrorCode UsnErrorCode { get; set; }

        public  bool Index { get => _settings.Paths.Contains(Name); }

        public string IndexStr { get => Index ? "是" : "否"; }

        public DriveInfo _driveInfo { get; set; }


        private readonly Settings _settings;

        public LoadingDriverInfo(Settings settings)
        {
            this._settings = settings;
        }

    }

    public class Loading
    {

        public ObservableCollection<LoadingDriverInfo> Drivers { get; set; } = new ObservableCollection<LoadingDriverInfo>();


        private Settings settings;
        public PluginInitContext context;

        public FileAndDirectoryEntry[] Files { get; set; }


        public bool IsLoading { get; set; }


        public Loading(Settings settings)
        {
            this.settings = settings;

            IsLoading = false;

        }



        public void Load()
        {
   

            if (IsLoading)
            {
                return;
            }
            IsLoading = true;

            LoadDriver();

            if (context.CurrentPluginMetadata.Disabled)
            {
                IsLoading = false;
                return;
            }
            LoadUSN();


        }


        private void LoadDriver()
        {
            DriveInfo[] volumes = DriveInfo.GetDrives();
            Drivers.Clear();

            foreach (DriveInfo di in volumes)
            {
                LoadingDriverInfo info = new LoadingDriverInfo(settings);
                info.Name = di.Name;
                info.DriveFormat = di.DriveFormat;
                if (di.IsReady && 0 == string.Compare(di.DriveFormat, "ntfs", true))
                {
                    var usnOperator = new UsnOperator(di);
                    info.UsnErrorCode = usnOperator.QueryUSNJournal();
                    if (info.UsnErrorCode == UsnErrorCode.SUCCESS && info.Index)
                    {
                        info._driveInfo = di;
                    }
                    
                }
                Drivers.Add(info);
            }

            volumes = null;
        }

        private void LoadUSN()
        {

            Task.Run(() => { ListFilesThreadStart(); });

            //Thread usnJournalThread = new Thread(ListFilesThreadStart);
            //usnJournalThread.Start();
        }


        private void ListFilesThreadStart()
        {


            var results = new List<FileAndDirectoryEntry>();

            Files = null;

            foreach (LoadingDriverInfo driver in Drivers)
            {
                if (null == driver._driveInfo)
                {
                    continue;
                }

                try
                {
                    Engine.GetFilesAndDirectories(driver._driveInfo, out List<FileAndDirectoryEntry> result, out UsnErrorCode code);
                    driver.UsnErrorCode = code;
                    var re = result.Where(p => { foreach (string filter in settings.Suffixes) { if (p.FileName.EndsWith("." + filter)) return true; } return false; });

                    results.AddRange(re);

                    Log.Info($"|Saber.Plugin.NtfsSearch.Loading.ListFilesThreadStart|加载 {driver.Name} USN 完成, Code: {code}, 检索 Count: {re.Count()}");

                    result = null;
                    re = null;
                }
                catch (Exception excptn)
                {
                    Log.Exception($"|Saber.Plugin.NtfsSearch.Loading.ListFilesThreadStart|加载 {driver.Name} 索引时异常", excptn);
                }

            }

            Files = results.ToArray();
            results = null;



            GC.Collect();


            IsLoading = false;

        }



    }
}
